﻿using OAS.Application.UserApp.Dtos;
using OAS.Core;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing;
using System.Text;
using System.Security.Cryptography;
using System.Net;
using System.Drawing.Printing;
using OAS.Application.System.Dtos;
using System.Linq.Expressions;
using Furion.LinqBuilder;
using System.Data;
using System.Xml.Linq;

namespace OAS.Application;

public class UserService : Repository<User>, IUserService, ITransient
{
    public async Task<List<User>> GetAllUser()
    {
        Expression<Func<User, Department, bool>> sqlWhere = Expressionable.Create<User, Department>()
              .AndIF(UserContext.CurrentUser.RoleName != "总经理" && UserContext.CurrentUser.RoleName != "主管" && !UserContext.IsAdmin, (o, department) => o.UserName == UserContext.CurrentUser.UserName)
              .AndIF(UserContext.CurrentUser.RoleName == "主管", (o, department) => o.Department_Id == UserContext.CurrentUser.Department_Id)
              .ToExpression();
        return await AsQueryable().LeftJoin<Department>((o, department) => o.Department_Id == department.Department_Id).Where(sqlWhere).IgnoreColumns(o => o.Password).ToListAsync();
    }
    public async Task<List<User>> GetAllUserByDepartment()
    {
        Expression<Func<User, Department, bool>> sqlWhere = Expressionable.Create<User, Department>()
              .AndIF(UserContext.CurrentUser.RoleName != "总经理" && !UserContext.IsAdmin, (o, department) => o.Department_Id == UserContext.CurrentUser.Department_Id)
              .ToExpression();
        return await AsQueryable().LeftJoin<Department>((o, department) => o.Department_Id == department.Department_Id).Where(sqlWhere).IgnoreColumns(o => o.Password).ToListAsync();
    }
    public async Task<object> GetUserList(DtoQuery dto)
    {
        Expression<Func<User, Role, Department, bool>> sqlWhere = Expressionable.Create<User, Role, Department>() //创建表达式
              .AndIF(!string.IsNullOrEmpty(dto.KeyWord), (o, role, department) => o.UserName.Contains(dto.KeyWord) || o.UserTrueName.Contains(dto.KeyWord)
                      || o.Tel.Contains(dto.KeyWord) || role.RoleName.Contains(dto.KeyWord) || department.DepartmentName.Contains(dto.KeyWord))
              .AndIF(UserContext.CurrentUser.RoleName != "总经理" && UserContext.CurrentUser.RoleName != "主管" && !UserContext.IsAdmin, (o, role, department) => o.UserName == UserContext.CurrentUser.UserName)
              .AndIF(UserContext.CurrentUser.RoleName == "主管", (o, role, department) => o.Department_Id == UserContext.CurrentUser.Department_Id)
              .ToExpression();
        RefAsync<int> total = 0;//REF和OUT不支持异步,想要真的异步这是最优解
        List<User> list =  await AsQueryable()
         .LeftJoin<Role>((o, role) => o.Role_Id == role.Role_Id)//多个条件用&&
         .LeftJoin<Department>((o, role, department) => o.Department_Id == department.Department_Id)
         .Where(sqlWhere)
            .IgnoreColumns(o=>o.Password)
            .ToPageListAsync(dto.PageIndex, dto.PageSize, total);//ToPageAsync
        return new { list, total};
    }
    public DtoUserInfo GetUserInfo(string userName)
    {
        return AsQueryable()
         .LeftJoin<Role>((o, role) => o.Role_Id == role.Role_Id)//多个条件用&&
         .LeftJoin<Department>((o, role, department) => o.Department_Id == department.Department_Id)
         .Where(o => o.UserName == userName)
         .Select((o, role, department) => new DtoUserInfo
         {
             User_Id = o.User_Id,
             UserName = o.UserName,
             Role_Id = role.Role_Id,
             RoleName = role.RoleName,
             Department_Id = department.Department_Id,
             DepartmentName = department.DepartmentName,
             UserTrueName = o.UserTrueName,
             Gender = o.Gender,
             Tel = o.Tel,
             Email = o.Email,
             BirthDate = o.BirthDate,
             RegisterDate = o.RegisterDate,
         }).First();
    }
    public async Task AddNewUser(User user)
    {
        if (base.AsQueryable().Any(o => o.UserName == user.UserName)) throw Oops.Oh("用户名已存在");
        user.Password = MD5Encrypt64(user.Password);
        user.RegisterDate = DateTime.Now;
        await base.InsertAsync(user);
    }
    public async Task UpdateUser(User user)
    {
        //if (base.AsQueryable().Any(o => o.UserName == user.UserName)) throw Oops.Oh("用户名已存在");
        await base.AsUpdateable(user).IgnoreColumns(it => new { it.Password }).ExecuteCommandAsync();
    }
    public async Task DeleteUser(string[] ids)
    {
        await base.DeleteByIdsAsync(ids);
    }
    public async Task PasswordChange(DtoPwd dto)
    {
        var user = await base.GetFirstAsync(o => o.UserName.Equals(dto.UserName) && o.Password.Equals(MD5Encrypt64(dto.Old)));
        if (user is null)
        {
            throw Oops.Oh("原密码错误");
        }
        else
        {
            user.Password = MD5Encrypt64(dto.New);
            await base.UpdateAsync(user);
        }
    }
    public string MD5Encrypt64(string password)
    {
        string cl = password;
        //string pwd = "";
        MD5 md5 = MD5.Create(); //实例化一个md5对像
                                // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
        byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
        return Convert.ToBase64String(s);
    }
}
